﻿using KnBinarySerializer.Field;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace KnBinarySerializer
{
    internal class DictionaryFormatter : IFormatter, IItemFormatter
    {
        public Type GetHandleType()
        {
            return null;
        }

        public byte GetKey()
        {
            return (byte)2;
        }
        public bool IsFixLen()
        {
            return false;
        }
        private Type genDictionaryType(BinarySerializeManager content,Type type, byte keyKey, byte valKey)
        {
            if (type == null)
            {
                //Creating the Dictionary.
                Type typeDict = typeof(Dictionary<,>);

                Type keyType = content.GetFormatter(keyKey).GetHandleType();
                Type valueType =content.GetFormatter(valKey).GetHandleType();
                //Creating KeyValue Type for Dictionary.
                Type[] typeArgs = { keyType, valueType };

                //Passing the Type and create Dictionary Type.
                type = typeDict.MakeGenericType(typeArgs);
            }

            return type;
        }
        public object ReadBytes(BinarySerializeManager content, int maxLen, Type type)
        {            
            type = genDictionaryType(content,type, content.ReadByte(), content.ReadByte());

            System.Collections.IDictionary list = (System.Collections.IDictionary)ClassSerialContext.CreateObject(type);
            //Type targetType = obj.GetType();
            Type[] argTypes = type.GetGenericArguments();
            //Type subType = type.GetGenericTypeDefinition().MakeGenericType(argTypes);
            int cnt = content.ReadInt();
            for(int i=0; i < cnt; i++)
            {
                //IFormatter formater = FormatterFactory.GetFormatter(content.ReadByte());
                ////读取长度 key
                //int len = content.ReadInt();
                //index += 5;
                ////byte[] subContent = new byte[len];
                ////Array.Copy(content, index, subContent, 0, len);
                //object key = formater.ReadBytes(content,len, argTypes[0]);
                object key = content.DeSerializeObject(argTypes[0]);
                //index += len;
                //formater = FormatterFactory.GetFormatter(content.ReadByte());
                ////读取长度 val
                //len = content.ReadInt();
                //index += 5;
                ////subContent = new byte[len];
                ////Array.Copy(content, index, subContent, 0, len);
                //object val = formater.ReadBytes(content,len, argTypes[1]);
                object val = content.DeSerializeObject(argTypes[1]);
                list.Add(key,val);                
            }
            return list;
        }

        public int WriteBytes(BinarySerializeManager serial, object obj)
        {
            Type[] itemTypes = obj.GetType().GetGenericArguments();
            //写入类型
            byte keyKey = serial.GetFormatter(itemTypes[0]).GetKey();
            byte valKey = serial.GetFormatter(itemTypes[1]).GetKey();
            serial.Write(keyKey);
            serial.Write(valKey);
            System.Collections.IEnumerable list = (System.Collections.IEnumerable)obj;
            int cnt = 0;
            foreach (var item in list)
                cnt++;
            //写入对象数量 
            serial.Write(cnt);
            foreach (var item in list)
            {                
                Type type = item.GetType();
                PropertyInfo key = type.GetProperty("Key");
                PropertyInfo val = type.GetProperty("Value");
                serial.SerializeObject(key.GetValue(item,null));
                //val值有可能为null，SerializeObject对于null是不作处理
                object keyVal = val.GetValue(item, null);
                if (keyVal == null)
                    serial.WriteNull();
                else
                    serial.SerializeObject(keyVal);
            }
            return -1;
        }

        public void ReadBytes(BinarySerializeManager content, int maxLen, object targetList)
        {
            long start = content.GetPosition();            
            Type type = genDictionaryType(content,targetList.GetType(), content.ReadByte(), content.ReadByte());

            System.Collections.IDictionary list = (System.Collections.IDictionary)targetList;
            //Type targetType = obj.GetType();
            Type[] argTypes = type.GetGenericArguments();
            //Type subType = type.GetGenericTypeDefinition().MakeGenericType(argTypes);
            //读取个数
            int cnt = content.ReadInt();
            for(int i = 0; i < cnt; i++)
            {                
                object key = content.DeSerializeObject(argTypes[0]);
                object val = content.DeSerializeObject(argTypes[1]);
                list.Add(key, val);
            }
        }
    }
}
